#include "lxz_config.h"

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

#ifdef LXZAT_WIN32
#include <io.h>
#include <winsock2.h>
#include <windows.h>
#endif /* LXZAT_WIN32 */

#ifdef LXZAT_LINUX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <unistd.h>
#endif /* LXZAT_LINUX */

#include "lxz_types.h"
#include "os_port.h"
#include "lxz_runlog.h"
#include "lxz_debug.h"
#include "lxz_ftp.h"

#define true 	1
#define false 	0
#define bool 	int
#define PORT    21

#define COMMAND_SIZE    256
#define MAX_RECV_SIZE    1024 << 1

static bool ftp_set_nonblock(uint32 socketHandle)
{
#ifdef _WIN32
    unsigned long ul = 1; 
    ioctlsocket(socketHandle, FIONBIO, &ul); 
#else
    int flag = fcntl(socketHandle, F_GETFL);
    flag |= O_NONBLOCK;
    if (fcntl(socketHandle, F_SETFL, flag) == -1)
    {
        return false;
    }
#endif
    return true;
}

static sint32 eftp_ftpcmd_f_write(uint32 socketHandle, const char *command)
{
    char sendCommand[COMMAND_SIZE] = {0x00};
    
    return_val_if_fail(socketHandle != -1, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    sprintf(sendCommand, "%s\r\n", command);
    osp_socket_f_write(socketHandle, sendCommand, strlen(sendCommand));

    OS_DBG_DBG(("eftp:eftp_ftpcmd_f_write:%s\r\n", command));
    OS_DBG_LOG(("eftp:eftp_ftpcmd_f_write:%s\r\n", command));

    return LXZAT_TRUE;
}

static long 
eftp_ftpcmd_f_wait(uint32 socketHandle, char *recvBuf, sint32 recvMaxSize, sint32 i_code_response)
{
    sint32 i_err_code = 0;
    
    sint32 i_len_read = 0;
    sint32 i_len_allread = 0;
    sint32 i_len_freespace = 0;
    char* p_tmp_substring = NULL;
    char* p_tmp_string = recvBuf;

    char p_buf_errcode[16];
    
    if (socketHandle == -1)
    {
        i_err_code = -1;
        return i_err_code;
    }
    
    if (recvBuf == NULL)
    {
        i_err_code = -1;
        return i_err_code;
    }
    
    memset(p_buf_errcode, 0, sizeof(p_buf_errcode));
    sprintf(p_buf_errcode, "%ld", i_code_response);
    strcat(p_buf_errcode, " ");

    do {
        i_len_freespace = recvMaxSize - i_len_allread;
        i_len_read = osp_socket_f_read(socketHandle, recvBuf + i_len_allread, i_len_freespace);
        if(i_len_read <= 0)
        {
            i_err_code = 0;
            break;
        }
        i_len_allread = i_len_allread + i_len_read;
        
        p_tmp_substring = strstr(recvBuf,p_buf_errcode);
        if (p_tmp_substring != NULL)
        {
            i_err_code = 1;
            i_len_freespace = recvMaxSize - i_len_allread;
            osp_socket_f_read(socketHandle, recvBuf + i_len_allread, i_len_freespace);
            break;
        }

        if (i_len_allread >= 4)
        {
            if (p_tmp_string[3] == ' ')
            {
                i_err_code = -1;
                osp_socket_f_read(socketHandle, recvBuf + i_len_allread, recvMaxSize);
                break;
            }

            p_tmp_substring = strstr(p_tmp_string, "\r\n");
            if (p_tmp_substring != NULL)
            {
                p_tmp_string = p_tmp_substring + 2;
            }
        }
    } while (i_len_allread < recvMaxSize);
    
    return i_err_code;
}

static long 
ftp_recv_data_command(uint32 socketHandle, char *recvBuf, sint32 recvMaxSize)
{
    sint32 recvSize = 0;

    sint32 totalSize = 0;
    
    return_val_if_fail(socketHandle != -1, -1);
    return_val_if_fail(recvBuf != NULL, -1);
    
    
    while(1)
    {
        OS_DBG_DBG(("%s,recvMaxSize = %d\r\n",__func__, recvMaxSize));
        recvSize = recv(socketHandle, recvBuf + totalSize, recvMaxSize - totalSize, 0);
        OS_DBG_DBG(("%s,recvBuf = %d\r\n",__func__, recvSize));
        OS_DBG_DBG(("%s,recvBuf = %s\r\n",__func__, recvBuf));
        if (totalSize >= recvMaxSize) {
            break;
        } else {
            if (recvSize > 0) {
                totalSize += recvSize;
            }
        }
    }
    
    while(1)
    {
        recvSize = recv(socketHandle, recvBuf + totalSize, recvMaxSize - totalSize, 0);
        if (recvSize > 0) 
        {
            totalSize += recvSize;
        }
        else
        {
            break;
        }
        
        if (totalSize >= recvMaxSize) 
        {
            break;
        }
        
    }
    return totalSize;
}

static sint32 eftp_init(lxz_easyftp_t *p_eftp_ctxt, int mode, int timeout, int ftp_type)
{
    if (NULL == p_eftp_ctxt)
    {
        return LXZAT_FALSE;
    }
    
    p_eftp_ctxt->it_cmd_socket = -1;
    p_eftp_ctxt->it_data_socket       = -1;
    p_eftp_ctxt->it_secs_timeout       = timeout;
    p_eftp_ctxt->it_code_reply       = -1;
    p_eftp_ctxt->it_mode_transport      = (mode==0?E_EFTM_PORT:E_EFTM_PASV);
    memset(p_eftp_ctxt->replyString, 0x00, EFTP_REPLY_SIZE);

    return LXZAT_TRUE;
}

static sint32 eftp_ftpcmd_f_clean(lxz_easyftp_t *p_eftp_ctxt)
{
    sint32 i_nb_fds = 0;
    char recvBuf[MAX_RECV_SIZE] = {0x00};
    
    if (p_eftp_ctxt == NULL)
    {
        return LXZAT_FALSE;
    }
    
    p_eftp_ctxt->it_code_reply = -1;
    memset(p_eftp_ctxt->replyString, 0x00, sizeof(p_eftp_ctxt->replyString));
    
    osp_socket_f_read(p_eftp_ctxt->it_cmd_socket, recvBuf, MAX_RECV_SIZE);
    OS_DBG_DBG(("eftp:eftp_ftpcmd_f_clean:%s\r\n", recvBuf));
    OS_DBG_LOG(("eftp:eftp_ftpcmd_f_clean:%s\r\n", recvBuf));

    return LXZAT_TRUE;
}

static sint32 eftp_ftpcmd_f_read(lxz_easyftp_t *p_eftp_ctxt, sint32 i_code_response)
{
    sint32 i_err_code = 0;
    sint32 i_nb_bytes = 0;

    uint32 i_cur_ticks = 0;
    uint32 i_mark_ticks = 0;

    char recvBuf[1024] = {0x00};
    
    if (p_eftp_ctxt == NULL)
    {
        return i_err_code;
    }
    
    p_eftp_ctxt->it_code_reply = -1;
    memset(p_eftp_ctxt->replyString, 0x00, EFTP_REPLY_SIZE);
    

    i_cur_ticks = osp_time_tickget();
    i_mark_ticks = i_cur_ticks;
    
    while ((p_eftp_ctxt->it_secs_timeout * 1000) > (i_cur_ticks - i_mark_ticks))
    {
        i_nb_bytes = osp_socket_f_getavailable(p_eftp_ctxt->it_cmd_socket);
        if (i_nb_bytes > 0)
        {
            memset(recvBuf, 0, sizeof(recvBuf));
            i_err_code = eftp_ftpcmd_f_wait(p_eftp_ctxt->it_cmd_socket, recvBuf, sizeof(recvBuf), i_code_response);
            OS_DBG_DBG(("eftp:eftp_ftpcmd_f_read:i_err_code:%d\r\n", i_err_code));
            OS_DBG_LOG(("eftp:eftp_ftpcmd_f_read:i_err_code:%d\r\n", i_err_code));
            
            if (i_err_code > 0)
            {
                strncpy(p_eftp_ctxt->replyString, recvBuf, strlen(recvBuf));
                OS_DBG_LOG(("eftp:eftp_ftpcmd_f_read:%d,get!\r\n", i_code_response));
                break;
            }
            else
            {
                if (i_err_code < 0)
                {
                    OS_DBG_DBG(("eftp:eftp_ftpcmd_f_read:i_err_code:%d, unknown error\r\n", i_err_code));
                    OS_DBG_LOG(("eftp:eftp_ftpcmd_f_read:i_err_code:%d, unknown error\r\n", i_err_code));
                    break;
                }
            }
        }
        
        i_cur_ticks = osp_time_tickget();
        osp_timer_f_sleep(1);
    }

    OS_DBG_DBG(("eftp:eftp_ftpcmd_f_read:recvBuf:%s\r\n", recvBuf));
    OS_DBG_LOG(("eftp:eftp_ftpcmd_f_read:recvBuf:%s\r\n", recvBuf));

    return i_err_code;
}

static sint32 ftp_send_and_recv_reply(lxz_easyftp_t *p_eftp_ctxt, const char *command, sint32 i_code_response)
{
    sint32 i_err_code = 0;

    if (p_eftp_ctxt == NULL)
    {
        return LXZAT_FALSE;
    }

    if (command == NULL)
    {
        return LXZAT_FALSE;
    }

    eftp_ftpcmd_f_clean(p_eftp_ctxt);

    eftp_ftpcmd_f_write(p_eftp_ctxt->it_cmd_socket, command);
    memset(p_eftp_ctxt->replyString, 0x00, sizeof(p_eftp_ctxt->replyString));
    i_err_code = eftp_ftpcmd_f_read(p_eftp_ctxt, i_code_response);

    return i_err_code;
}

static lxz_easyftp_t *eftp_connect_server(sint08 *ipAddress, uint16 port, int mode, int timeout, int ftp_type)
{
    lxz_easyftp_t *p_eftp_ctxt = NULL;

    sint32 i_err_code = 0;
    
    if (ipAddress == NULL)
    {
        OS_DBG_DBG(("eftp:eftp_connect_server:ipAddress == NULL\r\n"));
        OS_DBG_LOG(("eftp:eftp_connect_server:ipAddress == NULL\r\n"));
        return NULL;
    }
    
    p_eftp_ctxt = (lxz_easyftp_t *)malloc(sizeof(lxz_easyftp_t));
    if (p_eftp_ctxt == NULL)
    {
        OS_DBG_DBG(("eftp:eftp_connect_server:p_eftp_ctxt == NULL\r\n"));
        OS_DBG_LOG(("eftp:eftp_connect_server:p_eftp_ctxt == NULL\r\n"));
        return NULL;
    }
    
    memset(p_eftp_ctxt,0x00,sizeof(lxz_easyftp_t));
    eftp_init(p_eftp_ctxt, mode, timeout, ftp_type);
    
    p_eftp_ctxt->it_cmd_socket = osp_socket_f_open(2/*AF_INET*/, 1/*SOCK_STREAM*/,0);
    if (p_eftp_ctxt->it_cmd_socket == -1)
    {
        OS_DBG_DBG(("eftp:eftp_connect_server:osp_socket_f_open failure\r\n"));
        OS_DBG_LOG(("eftp:eftp_connect_server:osp_socket_f_open failure\r\n"));
        if (p_eftp_ctxt != NULL)
        {
            free(p_eftp_ctxt);
            p_eftp_ctxt = NULL;
        }
        
        return NULL;
    }
    
    i_err_code = osp_socket_f_connect(p_eftp_ctxt->it_cmd_socket, ipAddress, port);
    if (i_err_code != 1)
    {
        OS_DBG_DBG(("eftp:eftp_connect_server:osp_socket_f_connect:%s failure\r\n", ipAddress));
        OS_DBG_LOG(("eftp:eftp_connect_server:osp_socket_f_connect:%s failure\r\n", ipAddress));
        if (p_eftp_ctxt != NULL)
        {
            free(p_eftp_ctxt);
            p_eftp_ctxt = NULL;
        }
        
        return NULL;
    }
    
    osp_socket_f_nonblock(p_eftp_ctxt->it_cmd_socket, 1);
    OS_DBG_DBG(("eftp:eftp_connect_server:osp_socket_f_connect:%s successfully\r\n", ipAddress));
    OS_DBG_LOG(("eftp:eftp_connect_server:osp_socket_f_connect:%s successfully\r\n", ipAddress));
    
    return p_eftp_ctxt;
}

static sint32 eftp_ftpcmd_f_login(lxz_easyftp_t *p_eftp_ctxt, const char *ipAddress, const char *username, const char *passwd)
{
    sint32 i_err_code = 0;
    
    char command[COMMAND_SIZE];
    
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(ipAddress != NULL, LXZAT_FALSE);
    
    memset(command, 0x00, sizeof(command));
    sprintf(command, "USER %s", username);
    
    i_err_code = ftp_send_and_recv_reply(p_eftp_ctxt, command, 331);
    if (i_err_code <= 0)
    {
        OS_DBG_DBG(("eftp:eftp_ftpcmd_f_login:USER,i_err_code=%d\r\n", i_err_code));
        OS_DBG_LOG(("eftp:eftp_ftpcmd_f_login:USER,i_err_code=%d\r\n", i_err_code));
        return LXZAT_FALSE;
    }
    
    memset(command, 0x00, sizeof(command));
    sprintf(command, "PASS %s", passwd);
    i_err_code = ftp_send_and_recv_reply(p_eftp_ctxt, command, 230);
    if (i_err_code <= 0)
    {
        OS_DBG_DBG(("eftp:eftp_ftpcmd_f_login:PASS,i_err_code=%d\r\n", i_err_code));
        OS_DBG_LOG(("eftp:eftp_ftpcmd_f_login:PASS,i_err_code=%d\r\n", i_err_code));
        return LXZAT_FALSE;
    }

    return LXZAT_TRUE;
}

static sint32 eftp_ftpcmd_f_cmdsyst(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return ftp_send_and_recv_reply(p_eftp_ctxt, "SYST", 215);
}

static sint32 ftp_set_transfer_type(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return ftp_send_and_recv_reply(p_eftp_ctxt, command, 200);
}

static sint32 ftp_set_transfer_mode(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return ftp_send_and_recv_reply(p_eftp_ctxt, command, 200);
}

static bool ftp_pasv(lxz_easyftp_t *p_eftp_ctxt)
{
    sint32 i_err_code = 0;

    sint32 i_nb_string = 0;
    char pasv[32] = {0x00};
    char hostAddr[16] = {0x00};
    sint32 addr_1, addr_2, addr_3, addr_4, port_1, port_2;
    uint16 i_dst_port = 0;
    
    return_val_if_fail(p_eftp_ctxt != NULL, false);
    
    p_eftp_ctxt->it_data_socket = osp_socket_f_open(2/*AF_INET*/, 1/*SOCK_STREAM*/,0);
    i_err_code = ftp_send_and_recv_reply(p_eftp_ctxt, "PASV", 227);
    if (i_err_code <= 0)
    {
        return i_err_code;
    }

    i_nb_string = strchr(p_eftp_ctxt->replyString, ')') - strchr(p_eftp_ctxt->replyString, '(');
    strncpy(pasv, strchr(p_eftp_ctxt->replyString, '('), i_nb_string + 1);
    sscanf(pasv, "(%ld,%ld,%ld,%ld,%ld,%ld)", &addr_1, &addr_2, &addr_3, &addr_4, &port_1, &port_2);

    i_dst_port = ((uint16)((port_1 & 0x00FF) << 8)) + (uint16)(port_2 & 0x00FF);
    sprintf(hostAddr, "%ld.%ld.%ld.%ld", addr_1, addr_2, addr_3, addr_4);
    OS_DBG_DBG(("eftp:connect to:%s:%d\r\n", hostAddr, i_dst_port));
    OS_DBG_LOG(("eftp:connect to:%s:%d\r\n", hostAddr, i_dst_port));

    i_err_code = osp_socket_f_connect(p_eftp_ctxt->it_data_socket, hostAddr, i_dst_port);
    if (i_err_code == 0)
    {
        return LXZAT_FALSE;
    }

    osp_socket_f_nonblock(p_eftp_ctxt->it_data_socket, 1);
    
    return LXZAT_TRUE;
}

#define UC(arg)    ( ( (int)arg) & 0xff)
static bool ftp_port(lxz_easyftp_t *p_eftp_ctxt)
{
    
    char *addr, *port;
    char command[256] = {0x00};
    struct sockaddr_in dataAddr;
    short int i_rand_ip_last;
    size_t len = sizeof(dataAddr);
    
    return_val_if_fail(p_eftp_ctxt != NULL, false);
    
    if (getsockname(p_eftp_ctxt->it_cmd_socket, (struct sockaddr *)&dataAddr, &len) != 0)
    {
        return false;
    }
    p_eftp_ctxt->it_data_socket = osp_socket_f_open(2/*AF_INET*/, 1/*SOCK_STREAM*/,0);
    if (p_eftp_ctxt->it_data_socket == -1)
    {
        return false;
    }
    i_rand_ip_last = (short int)rand();
    i_rand_ip_last = i_rand_ip_last < 1024?i_rand_ip_last+1024:i_rand_ip_last;
    
    dataAddr.sin_port = htons(i_rand_ip_last);
    
    if (bind(p_eftp_ctxt->it_data_socket, (struct sockaddr *)&dataAddr, len) != 0)
    {
        return false;
    }
    if (getsockname(p_eftp_ctxt->it_data_socket, (struct sockaddr *)&dataAddr, &len) != 0)
    {
        return false;
    }
    
    if (osp_socket_f_listen(p_eftp_ctxt->it_data_socket, 1) != 1)
    {
        return false;
    }
    addr = (char *)&dataAddr.sin_addr;
    port = (char *)&dataAddr.sin_port;
    sprintf(command, "PORT %d,%d,%d,%d,%d,%d",
        UC(addr[0]), UC(addr[1]), UC(addr[2]), UC(addr[3]),
        UC(port[0]), UC(port[1]) );
    
    if (ftp_send_and_recv_reply(p_eftp_ctxt, command, 200) != LXZAT_TRUE)
    {
        return false;
    }
    
    return true;
}

static bool ftp_init_data_channel(lxz_easyftp_t *p_eftp_ctxt)
{
    return_val_if_fail(p_eftp_ctxt != NULL, false);
    
    if (p_eftp_ctxt->it_data_socket != -1)
    {
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
    }
    if (p_eftp_ctxt->it_mode_transport == E_EFTM_PASV)
    {
        return ftp_pasv(p_eftp_ctxt);
    }
    else
    {
        return ftp_port(p_eftp_ctxt);
    }
    return false;
}

static bool ftp_build_data_channel(lxz_easyftp_t *p_eftp_ctxt)
{
    uint32 socketHandle;
    
    return_val_if_fail(p_eftp_ctxt != NULL, false);
    
    if (p_eftp_ctxt->it_mode_transport == E_EFTM_PASV)
    {
        return true;
    }
    
    if (osp_socket_f_select(p_eftp_ctxt->it_data_socket, OSP_EVENT_READ, p_eftp_ctxt->it_secs_timeout) <= 0)
    {
        return false;
    }
    socketHandle = osp_socket_f_accept(p_eftp_ctxt->it_data_socket);
    if (socketHandle == -1)
    {
        return false;
    }
    else
    {
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
        p_eftp_ctxt->it_data_socket = socketHandle;
        osp_socket_f_nonblock(p_eftp_ctxt->it_data_socket, 1);
        return true;
    }
    return false;
}


static bool ftp_recv_data_channnel(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    
    if (ftp_init_data_channel(p_eftp_ctxt) != true)
    {
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
        return false;
    }
    if (ftp_send_and_recv_reply(p_eftp_ctxt, command, 150) != LXZAT_TRUE)
    {
        return false;
    }
    if (ftp_build_data_channel(p_eftp_ctxt) != true)
    {
        return false;
    }
    
    return true;
}

static sint32 ftp_recv_command_ack(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    sint32 i_err_code = 0;
    
#if 0
    if (ftp_init_data_channel(p_eftp_ctxt) != true)
    {
        i_err_code = -1;
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
        return i_err_code;
    }
#endif

    i_err_code = ftp_send_and_recv_reply(p_eftp_ctxt, command, 213);
    
    return i_err_code;
}

static sint32 ftp_list(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    char *recvBuf = NULL;

    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
#if 0
    recvBuf = ftp_recv_data_channnel(p_eftp_ctxt, command);
    if (recvBuf != NULL)
    {
        OS_DBG_DBG(("%s", recvBuf));
        
        if (recvBuf != NULL)
        {
            free(recvBuf);
            recvBuf = NULL;
        }
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
        eftp_ftpcmd_f_clean(p_eftp_ctxt)
    }
#endif
    return LXZAT_FALSE;
}

static sint32 ftp_size(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    ftp_recv_command_ack(p_eftp_ctxt, command);
    
    if (strlen(p_eftp_ctxt->replyString) != 0) {
        
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
        return LXZAT_TRUE;
        
    }
    
    return LXZAT_FALSE;
}

static int ftp_string_analysis(const char *command,char cmd[][10],char segm_char)
{
    char *ptr =NULL;
    char *temp = (char *)command;
    int i = 0;
    
    do{
        if ((ptr = strchr(temp,segm_char)) != NULL){
            memset(cmd[i],0x00,sizeof(cmd[i]));
            memcpy(cmd[i++],temp,ptr-temp);
            ptr++;
            temp = ptr;
        } else if (i != 0){
            strcpy(cmd[i++],temp);
        }
        
    }while(ptr);
    
    return i;
}

static sint32 ftp_resume(lxz_easyftp_t *p_eftp_ctxt, const char *command, char cmd[][10])
{
    char entercommand[256];
    
    if (ftp_string_analysis(command, cmd, ' ') == 0){
        return LXZAT_FALSE;
    }
    
    memset(entercommand,0x00,sizeof(entercommand));
    sprintf(entercommand,"%s %s","REST", cmd[2]);
    
    return ftp_send_and_recv_reply(p_eftp_ctxt, entercommand, 200);
    
}

static sint32 ftp_delete_file(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    return ftp_send_and_recv_reply(p_eftp_ctxt, command, 200);
}

static sint32 ftp_make_directory(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    return ftp_send_and_recv_reply(p_eftp_ctxt, command, 200);
}

static sint32 ftp_remove_directory(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    return ftp_send_and_recv_reply(p_eftp_ctxt, command, 200);
}

static sint32 ftp_change_directory(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    return ftp_send_and_recv_reply(p_eftp_ctxt, command, 200);
}

static sint32 eftp_ftpcmd_f_cmdpwd(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    return_val_if_fail(p_eftp_ctxt != NULL, LXZAT_FALSE);
    return_val_if_fail(command != NULL, LXZAT_FALSE);
    
    return ftp_send_and_recv_reply(p_eftp_ctxt, "PWD", 257);
}

static sint32 ftp_close(lxz_easyftp_t *p_eftp_ctxt, const char *command)
{
    if (p_eftp_ctxt == NULL)
    {
        return LXZAT_FALSE;
    }
    
    if (p_eftp_ctxt->it_cmd_socket != -1)
    {
        eftp_ftpcmd_f_write(p_eftp_ctxt->it_cmd_socket, command);
        osp_socket_f_close(p_eftp_ctxt->it_cmd_socket);
    }

    if (p_eftp_ctxt->it_data_socket != -1)
    {
        osp_socket_f_close(p_eftp_ctxt->it_data_socket);
    }

    if (p_eftp_ctxt != NULL)
    {
        free(p_eftp_ctxt);
        p_eftp_ctxt = NULL;
    }
    
    return LXZAT_TRUE;
}

lxz_easyftp_t * eftp_ftpsession_f_open(sint08 *ipAddress, uint16 ftp_port,
                                   const char *username, const char *passwd,
                                   int mode, int timeout, int ftp_type)
{
    lxz_easyftp_t *p_eftp_ctxt = NULL;
    
    p_eftp_ctxt = eftp_connect_server(ipAddress, ftp_port, mode, timeout, ftp_type);
    if (p_eftp_ctxt == NULL)
    {
        return NULL;
    }
    
    
    if (eftp_ftpcmd_f_login(p_eftp_ctxt, ipAddress,username,passwd) != LXZAT_TRUE)
    {
        osp_socket_f_close(p_eftp_ctxt->it_cmd_socket);
        if (p_eftp_ctxt != NULL)
        {
            free(p_eftp_ctxt);
            p_eftp_ctxt = NULL;
        }
        return NULL;
    }
    
    eftp_ftpcmd_f_cmdsyst(p_eftp_ctxt, NULL);
    if (ftp_type == 0)
    {
        ftp_set_transfer_mode(p_eftp_ctxt, "TYPE I");
    }
    else 
    {
        ftp_set_transfer_mode(p_eftp_ctxt, "TYPE A");
    }

    return p_eftp_ctxt;
}

void eftp_ftpsession_f_close(lxz_easyftp_t *p_eftp_ctxt)
{
    ftp_close(p_eftp_ctxt,"QUIT");
}

void eftp_ftpsession_f_cmdpwd(lxz_easyftp_t *p_eftp_ctxt)
{
    ftp_send_and_recv_reply(p_eftp_ctxt, "PWD", 257);
}

int  eftp_ftpsession_f_fSize(lxz_easyftp_t *p_eftp_ctxt)
{
    sint32 i_err_code = 0;

    char entercommand[256]={0};
    int fileSize=0;
    char *ptr;

    if (p_eftp_ctxt == NULL)
    {
        return LXZAT_FALSE;
    }
    
    OS_DBG_LOG(("eftp:eftp_ftpsession_f_fSize:it_cmd_socket:0x%08X\r\n",p_eftp_ctxt->it_cmd_socket));


    eftp_ftpcmd_f_clean(p_eftp_ctxt);
    
    sprintf(entercommand,"%s %s","SIZE", p_eftp_ctxt->get_filename);
    
    i_err_code = ftp_recv_command_ack(p_eftp_ctxt, entercommand);
    if (i_err_code < 0)
    {
        eftp_ftpdata_f_close(p_eftp_ctxt);
        return i_err_code;
    }
    
    ptr = strstr(p_eftp_ctxt->replyString,"213 ");
    if (ptr == NULL)
        return 0;
    
    ptr = ptr + 4;
    fileSize = atoi(ptr);

    return fileSize;
}

int eftp_ftpdata_f_ftpget(lxz_easyftp_t *p_eftp_ctxt,char* filename, int offset)
{
    sint32 i_err_code = 0;

    char entercommand[256];

    OS_DBG_DBG(("eftp:eftp_ftpdata_f_ftpget,create data-channel.\r\n"));
    OS_DBG_LOG(("eftp:eftp_ftpdata_f_ftpget,create data-channel.\r\n"));
    if (p_eftp_ctxt == NULL)
    {
        return 0;
    }

    if (filename == NULL)
    {
        return 0;
    }

    memset(entercommand,0x00,sizeof(entercommand));
    sprintf(entercommand,"%s %d","REST",offset);
    i_err_code = ftp_send_and_recv_reply(p_eftp_ctxt, entercommand, 350);
    if (i_err_code <= 0)
    {
        return i_err_code;
    }

    memset(entercommand,0x00,sizeof(entercommand));
    sprintf(entercommand,"%s %s","RETR",filename);
    
    if(!ftp_recv_data_channnel(p_eftp_ctxt, entercommand)){
        return 0;
    }
    
    return 1;
}

int eftp_ftpdata_f_read(lxz_easyftp_t *p_eftp_ctxt,char* p_buf_data, sint32 i_buf_size)
{
    sint32 i_len_curread = 0;

    if (p_eftp_ctxt == NULL)
    {
        return -1;
    }

    if (p_buf_data == NULL)
    {
        return -1;
    }

    i_len_curread = osp_socket_f_read(p_eftp_ctxt->it_data_socket, p_buf_data, i_buf_size);

    return i_len_curread;
}

int eftp_ftpdata_f_ftpput(lxz_easyftp_t *p_eftp_ctxt, char * filename)
{
    char entercommand[256];

    OS_DBG_DBG(("eftp:eftp_ftpdata_f_ftpput,create data-channel.\r\n"));
    OS_DBG_LOG(("eftp:eftp_ftpdata_f_ftpput,create data-channel.\r\n"));

    if (p_eftp_ctxt == NULL)
    {
        return 0;
    }

    if (filename == NULL)
    {
        return 0;
    }
    
    memset(entercommand,0x00,sizeof(entercommand));
    sprintf(entercommand,"%s %s","STOR",filename);
    strcpy(p_eftp_ctxt->put_filename, filename);
    
    if(!ftp_recv_data_channnel(p_eftp_ctxt, entercommand))
    {
        return 0;
    }

    return 1;
}

int eftp_ftpdata_f_write(lxz_easyftp_t *p_eftp_ctxt,char* p_buf_data, sint32 i_len_data)
{
    sint32 i_len_curwrite = 0;

    if (p_eftp_ctxt == NULL)
    {
        return -1;
    }

    if (p_buf_data == NULL)
    {
        return -1;
    }

    i_len_curwrite = osp_socket_f_write(p_eftp_ctxt->it_data_socket, p_buf_data, i_len_data);

    return i_len_curwrite;
}

int eftp_ftpcmd_f_close(lxz_easyftp_t *p_eftp_ctxt)
{
    if (p_eftp_ctxt == NULL)
    {
        return 1;
    }

    osp_socket_f_close(p_eftp_ctxt->it_cmd_socket);
    p_eftp_ctxt->it_cmd_socket = -1;
    p_eftp_ctxt->it_state_cmdsocket = E_EFSS_IDLE;
    return 1;
}

int eftp_ftpdata_f_close(lxz_easyftp_t *p_eftp_ctxt)
{
    if (p_eftp_ctxt == NULL)
    {
        return 1;
    }

    osp_socket_f_close(p_eftp_ctxt->it_data_socket);
    p_eftp_ctxt->it_data_socket = -1;
    
    p_eftp_ctxt->i_pos_tryread = 0;
    p_eftp_ctxt->i_len_tryread = 0;
    p_eftp_ctxt->i_len_trywrite = 0;
    p_eftp_ctxt->i_eof_trywrite = 0;
    p_eftp_ctxt->it_state_datasocket = E_EFSS_IDLE;

    return 1;
}